﻿using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using jSLApp.Client.ApplicationBase;
using jSLApp.Client.Controls;
using jSLApp.Client.MainService;
using jSLApp.Client.Security;
using jSLApp.Client.Workflow;
using jSLCore.Client.Presentation.Authorization;
using jSLCore.Client.Presentation.AuthorizeService;
using jSLCore.Client.Presentation.BaseControl.DialogMessage;
using jSLCore.Client.Presentation.BaseControl.Selection;
using jSLCore.Client.Presentation.jBinding.BaseConverters;
using jSLCore.Client.Presentation.jBinding.BaseValidationRules;
using jSLCore.Client.Utility;

namespace jSLApp.Client.Forms
{
    public partial class FilmDetail : jSLCore.Client.Presentation.BaseControl.DialogControl
    {
        private readonly int _id;

        public FilmDetail(int id):this()
        {
            _id = id;
            DontProceedDetaultButtonOnce = true;
        }

        public FilmDetail()
        {
            InitializeComponent();

            Unloaded+=OnUnloaded;
        }

        private void OnUnloaded(object sender, RoutedEventArgs routedEventArgs)
        {
            if (relativeLoaderClient != null) relativeLoaderClient.Abort();
        }

        public override bool IsStandartOkCancelEnabled
        {
            get { return false; }
        }
        
        public override void LoadInitialData()
        {
            DoWork("Загрузка фильма",(sender, args) =>
                                         {
                                             args.Result = Communication.Proxy.GetFilm(args.Int);
                                         },(o, eventArgs) =>
                                                               {
                                                                if(eventArgs.Error==null)
                                                                {
                                                                    SetDataContext((Film) eventArgs.Result);
                                                                }
                                                               },_id);
        }

        public void SetDataContext(Film film)
        {
            Film = film;
            Bind();
            CheckIsFilmBought();
            CheckAge();
            CheckCanRate();
            DoWork(true, null, (sender, args) => LoadRelative());
        }

        private void CheckCanRate()
        {
            DoWork("Загрузка", (sender1, workEventArgs) =>
            {
                workEventArgs.Result = Communication.Proxy.CanRate(workEventArgs.Int);
            }, (o1, completedEventArgs) =>
            {
                if (completedEventArgs.Error == null)
                {
                    if ((bool)completedEventArgs.Result)
                    {
                        rateControl.IsReadOnly = false;
                        ToolTipService.SetToolTip(rateControl,"Оцените фильм");
                    }
                    else
                    {
                        rateControl.IsReadOnly = true;

                        if(jSecurity.IsAuthorized)
                        {
                            ToolTipService.SetToolTip(rateControl, "Вы уже оценивали этот фильм");
                        }
                        else
                        {
                            ToolTipService.SetToolTip(rateControl,"Войдите, что бы оценивать фильм");
                        }
                    }
                }
            }, _id);

        }

        private bool ratingControl_Loaded;
        

        private void CheckAge()
        {
            if(Film.AgeNeed && ! DataHelper.AgeDone)
            {
                var dlg = new QuestionBox("Данный фильм имеет возрастное ограничение. Фильм запрещён к показу лицам, не достигшим совершеннолетия. Вам уже исполнилось 18 лет?",QuestionBoxType.YesNo);
                dlg.ShowDialog(delegate(object sender, object data)
                                   {
                                       DataHelper.AgeDone = true;
                                       if(jSecurity.IsAuthorized)
                                       {
                                           DoWork("Сохранение возрастных настроек",(o, args) => Communication.Proxy.SetAgeOfCurrentUser(),(sender1, eventArgs) =>
                                                                                                        { });
                                       }
                                   },null,delegate(object sender, EventArgs args)
                                              {
                                                  InvokeCancelSelected();
                                              }, true,null);
            }
        }

        private void CheckIsFilmBought()
        {
            DoWork("Загрузка",(sender, args) =>
                                  {
                                      args.Result = Communication.Proxy.IsFilmReadyForCurrentUser(args.Int);
                                  },(o, eventArgs) =>
                                        {
                                            if((bool) eventArgs.Result)
                                                            {
                                                                player.SetSource(Film.SourceUri,false,Film.IsSmoothStreaming);
                                                                buyButton.Visibility = Visibility.Collapsed;
                                                            }
                                                            else
                                                            {
                                                                player.SetSource(Film.TrailerUri);
                                                                buyButton.Visibility = Visibility.Visible;
                                                            }

                                            SetHeader();
                                        },Film.id);
            
        }

        private void SetHeader()
        {
            player.Header = new Image { Stretch = Stretch.Uniform, Source = (ImageSource) new jImageSourceConverter().Convert(Film.BigImage,typeof(ImageSource),null,null)};
        }

        private void buy_Clicked(object sender, RoutedEventArgs e)
        {
            Buy();
        }

        private void Buy()
        {
            if (jSecurity.IsAuthorized)
            {

                var dlg = new QuestionBox(string.Format(@"Купить фильм ""{0}""?", Film.Name), QuestionBoxType.YesNo);
                dlg.ShowDialog(delegate(object o, object data)
                                   {
                                       var dlg2 =
                                           new QuestionBox(
                                               string.Format(
                                                   @"Вы собираетесь приобрести фильм ""{0}"" по цене ""{1}"". Эта сумма будет списана с вашего баланса. Фильм будет доступен в течении 14 дней.  Обязательно прочитайте договор оферты (внизу страницы) перед покупкой. Продолжить?",
                                                   Film.Name, Film.Price), QuestionBoxType.YesNo);
                                       dlg2.ShowDialog(delegate(object sender1, object data1)
                                                           {
                                                               DoWork("Покупка фильма",
                                                                      (o1, args) =>
                                                                      Communication.Proxy.CheckOut(args.Int),
                                                                      (sender2, eventArgs) =>
                                                                          {
                                                                              if (eventArgs.Error == null)
                                                                              {
                                                                                  CheckIsFilmBought();
                                                                              }
                                                                              MainContentContainer.Current.
                                                                                  CheckConstants();
                                                                          }, Film.id);
                                                           });
                                   });
            }
            else
            {
                MainContentContainer.Current.ParentApplicationContainer.ShowAuthorizationDialog(true,(o, data) =>
                                                                                                         {
                                                                                                             Buy();  
                                                                                                         });
            }
        }
        
        public Film Film
        {
            get { return (Film) DataContext; }
            set { DataContext = value; }
        }

        protected override void TrySetInitialFocus()
        {
            player.Focus();
        }

        private void editName_Clicked(object sender, MouseButtonEventArgs e)
        {
            if (SecurityBinding.HasPermission(Permission.ChangeFilmName))
            {

                var dlg = new jAskForStringBox("Введите название фильма:", Film.Name, false, new jNotEmptyStringRule(),
                                               null);

                dlg.ShowDialog(delegate(object o, object data)
                                   {
                                       var str = (string) data;
                                       DoWork("Смена названия фильма",
                                              (sender1, args) =>
                                              Communication.Proxy.SetFilmName(args.Int, (string) args.Params[1]),
                                              (o1, eventArgs) =>
                                                  {
                                                      if (eventArgs.Error == null)
                                                      {
                                                          Film.Name = str;
                                                      }
                                                  }, Film.id, str);

                                   });
            }

            
        }

        private void editEnName_Clicked(object sender, MouseButtonEventArgs e)
        {
            if (SecurityBinding.HasPermission(Permission.ChangeFilmName))
            {

                var dlg = new jAskForStringBox("Введите название фильма:", Film.EnName, false);

                dlg.ShowDialog(delegate(object o, object data)
                {
                    var str = (string)data;
                    DoWork("Смена латинского названия фильма",
                           (sender1, args) =>
                           Communication.Proxy.SetFilmEnName(args.Int, (string)args.Params[1]),
                           (o1, eventArgs) =>
                           {
                               if (eventArgs.Error == null)
                               {
                                   Film.EnName = str;
                               }
                           }, Film.id, str);

                });
            }
        }

        private void editPhoto_Clicked(object sender, RoutedEventArgs routedEventArgs)
        {
            if (SecurityBinding.HasPermission(Permission.ChangeFilmImage))
            {
                var dlg = new OpenFileDialog();
                if (dlg.ShowDialog().GetValueOrDefault(false))
                {
                    var stream = dlg.File.OpenRead();
                    if (stream.Length > 30000000)
                    {
                        ErrorBox.ShowDialog("Размер файла слишком большой");
                        return;
                    }

                    var bs = new byte[stream.Length];
                    stream.Read(bs, 0, (int) stream.Length);
                    stream.Close();

                    DoWork("Смена изображения", (o, args) =>
                                                    {
                                                        args.Result = Communication.Proxy.ChangeFilmImage(args.Int,
                                                                                                          (byte[])
                                                                                                          args.Params[1]);
                                                    }, (sender1, eventArgs) =>
                                                           {
                                                               if (eventArgs.Error == null)
                                                               {
                                                                   Film.BigImage = new Binary(){Bytes =  (byte[])eventArgs.Result};
                                                                   SetHeader();
                                                               }
                                                           }, Film.id, bs);
                }
            }
        }

        private void getPhoto_Clicked(object sender, RoutedEventArgs e)
        {
            var dlg = new SaveFileDialog();
            dlg.DefaultExt = "*.png";
            if (dlg.ShowDialog().GetValueOrDefault(false))
            {
                
                            try
                            {
                                using (var file = dlg.OpenFile())
                                {
                                    var buffer = Film.BigImage.Bytes;
                                    file.Write(buffer, 0, buffer.Length);
                                }
                            }
                            catch (Exception)
                            {
                                ErrorBox.ShowDialog("Не удалось сохранить файл");
                            }
            }
        }

        private void GetPoster_Clicked(object sender, RoutedEventArgs e)
        {
            var dlg = new SaveFileDialog();
            dlg.DefaultExt = "*.png";
            if(dlg.ShowDialog().GetValueOrDefault(false))
            {
                DoWork("Загрузка постера",(o, args) =>
                                              {
                                                  args.Result = Communication.Proxy.GetFilmLastPhoto(args.Int);
                                              },
                    (sender1, eventArgs) =>
                        {
                            if(eventArgs.Error==null)
                            {
                                try
                                {
                                    using(var file = dlg.OpenFile())
                                    {
                                        var buffer = (byte[])eventArgs.Result;
                                        file.Write(buffer,0,buffer.Length);
                                    }
                                }
                                catch (Exception)
                                {
                                    ErrorBox.ShowDialog("Не удалось сохранить файл");
                                }
                                
                            }
                        },Film.id);
            }
        }

        private void SetPoster_Clicked(object sender, RoutedEventArgs e)
        {
            if (SecurityBinding.HasPermission(Permission.ChangeImageScreen))
            {
                var dlg = new OpenFileDialog();
                if (dlg.ShowDialog().GetValueOrDefault(false))
                {
                    var stream = dlg.File.OpenRead();
                    if (stream.Length > 30000000)
                    {
                        ErrorBox.ShowDialog("Размер файла слишком большой");
                        return;
                    }

                    var bs = new byte[stream.Length];
                    stream.Read(bs, 0, (int) stream.Length);
                    stream.Close();

                    DoWork("Смена изображения", (o, args) =>
                                                    {
                                                        args.Result = Communication.Proxy.SetImageScreen(args.Int,
                                                                                                         (byte[])
                                                                                                         args.Params[1]);
                                                    }, (sender1, eventArgs) =>
                                                           {
                                                               if (eventArgs.Error == null)
                                                               {
                                                                   //InfoBox.ShowDialog("Постер сменен");
                                                               }
                                                           }, Film.id, bs);
                }
            }
        }

        private void editDescription_Clicked(object sender, MouseButtonEventArgs e)
        {
            if (SecurityBinding.HasPermission(Permission.ChangeFilmDescription))
            {
                var dlg = new jAskForStringBox("Укажите комментарий:", Film.Description, true);
                dlg.ShowDialog((o, data) =>
                                   {
                                       var str = (string) data;
                                       DoWork("Изменение комментария",
                                              (sender1, args) =>
                                              Communication.Proxy.SetFilmDescription(args.Int, (string) args.Params[1]),
                                              (o1, eventArgs) =>
                                                  {
                                                      if (eventArgs.Error == null)
                                                      {
                                                          Film
                                                              .
                                                              Description
                                                              =
                                                              str;
                                                      }
                                                  }, Film.id, str);
                                   });
            }
        }

        private void editYear_Clicked(object sender, MouseButtonEventArgs e)
        {
            if (SecurityBinding.HasPermission(Permission.ChangeFilmAdvanced))
            {
                var dlg = new jAskForStringBox("Укажите год:", Film.Year.GetValueOrDefault(200).ToString(), false,
                                               new jIsUnsignedIntegerRule(), null);
                dlg.ShowDialog((o, data) =>
                                   {
                                       var year = int.Parse(data.ToString());
                                       DoWork("Смена года издания",
                                              (sender1, args) =>
                                              Communication.Proxy.SetFilmYear(args.Int, (int) args.Params[1]),
                                              (o1, eventArgs) =>
                                                  {
                                                      if (eventArgs.Error == null)
                                                      {
                                                          Film
                                                              .
                                                              Year
                                                              =
                                                              year;
                                                      }
                                                  }, Film.id, year);
                                   });
            }
        }

        private void editPrice_Clicked(object sender, MouseButtonEventArgs e)
        {
            if (SecurityBinding.HasPermission(Permission.ChangeFilmAdvanced))
            {
                var dlg = new jAskForStringBox("Укажите цену:", Film.Price.ToString(), false, new jIsUnsignedDecimal(){CanBeZero = true},
                                               new jCurrencyConverter());
                dlg.ShowDialog((o, data) =>
                                   {
                                       var price = (decimal) data;

                                       DoWork("Смена цены",
                                              (sender1, args) =>
                                              Communication.Proxy.SetFilmPrice(args.Int, (decimal) args.Params[1]),
                                              (o1, eventArgs) =>
                                                  {
                                                      if (eventArgs.Error == null)
                                                      {
                                                          Film
                                                              .
                                                              Price
                                                              =
                                                              price;
                                                      }
                                                  }, Film.id, price);
                                   });
            }
        }

        private void editTags_Clicked(object sender, MouseButtonEventArgs e)
        {
            var dlg = new TagsDetail(Film.Tags);

            dlg.ShowDialog((o, data) =>
                               {
                                   var str = (string)data;
                                   DoWork("Смена тэгов",(sender1, args) => Communication.Proxy.SetFilmTags(args.Int,(string) args.Params[1]),(o1, eventArgs) =>
                                                                                                                                                 {
                                                                                                                                                     if(eventArgs.Error==null)
                                                                                                                                                     {
                                                                                                                                                         Film
                                                                                                                                                             .
                                                                                                                                                             Tags
                                                                                                                                                             =
                                                                                                                                                             str;
                                                                                                                                                         LoadRelative
                                                                                                                                                             ();
                                                                                                                                                     }
                                                                                                                                                 },Film.id,
                                       str);
                               });
        }

        private void editCountry_Clicked(object sender, MouseButtonEventArgs e)
        {
            var dlg = new jAskForStringBox("Укажите страны:", Film.Country, false);

            dlg.ShowDialog(delegate(object o, object data)
                               {
                                   var str = (string) data;
                                   DoWork("Смена страны",(sender1, args) => Communication.Proxy.SetFilmCountry(args.Int,(string) args.Params[1]),(o1, eventArgs) =>
                                                                                    {
                                                                                        if(eventArgs.Error==null)
                                                                                        {
                                                                                            Film.Country = str;
                                                                                        }
                                                                                    },Film.id,str);
                               });
        }

        MainServiceClient relativeLoaderClient;

        private void LoadRelative()
        {
            relBusy.IsBusy = true;
            relatedRequests.Children.Clear();
            if (relativeLoaderClient != null) relativeLoaderClient.Abort();

            var basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.None)
            {
                MaxBufferSize = 2147483647,
                MaxReceivedMessageSize = 2147483647,
                SendTimeout = new TimeSpan(1, 0, 0, 0),
                ReceiveTimeout = new TimeSpan(1, 0, 0, 0),
                TransferMode = TransferMode.StreamedResponse
            };
            var address = new EndpointAddress(new Uri(UIHelper.GetCurrentWebHostAddress() + "MainService.svc"));

            relativeLoaderClient = new MainServiceClient(basicHttpBinding, address);

            relativeLoaderClient.GetRelatedCompleted += (sender1, completedEventArgs) =>
                                                            {
                                                                if (completedEventArgs.Error == null)
                                                                {
                                                                    var films = completedEventArgs.Result;
                                                                    foreach (var film in films)
                                                                    {
                                                                            var filmScreen = new FilmScreen() { DataContext = film };

                                                                            relatedRequests.Children.Add(filmScreen);
                                                                    }
                                                                }
                                                                relBusy.IsBusy = false;
                                                            };



            relativeLoaderClient.GetRelatedAsync(Film.id);
        }

        private void recomendEdit_Clicked(object sender, RoutedEventArgs e)
        {
            
                DoWork("Смена рекомендации",
                       (o, args) => Communication.Proxy.SetFilmIsRecomended(args.Int, (bool) args.Params[1]),
                       (sender1, eventArgs) =>
                           {
                               if (eventArgs.Error != null)
                               {
                                   var checkBox = (CheckBox) sender;

                                   checkBox
                                       .
                                       IsChecked
                                       =
                                       !checkBox
                                            .
                                            IsChecked;
                               }
                           }, Film.id, !Film.IsModeratorRecomended); //! - стоит потому, что чекбокс еще не обновился
            
        }

        private void publicEdit_Clicked(object sender, RoutedEventArgs e)
        {
            DoWork("Смена публикации",(o, args) => Communication.Proxy.SetFilmIsPublic(args.Int,(bool) args.Params[1]),(sender1, eventArgs) =>
                                                                                                                           {
                                                                                                                               if(eventArgs.Error!=null)
                                                                                                                               {
                                                                                                                                   var checkBox = (CheckBox)sender;

                                                                                                                                   checkBox
                                                                                                                                       .
                                                                                                                                       IsChecked
                                                                                                                                       =
                                                                                                                                       !checkBox
                                                                                                                                            .
                                                                                                                                            IsChecked;
                                                                                                                               }
                                                                                                                           },Film.id,!Film.IsPublic);
        }

        private void ageEdit_Clicked(object sender, RoutedEventArgs e)
        {
            DoWork("Смена возрастного ограничения", (o, args) => Communication.Proxy.SetFilmIsAgeNeed(args.Int, (bool)args.Params[1]), (sender1, eventArgs) =>
            {var checkBox = (CheckBox)sender;
                if (eventArgs.Error != null)
                {
                    

                    checkBox
                        .
                        IsChecked
                        =
                        !checkBox
                             .
                             IsChecked;
                }
                else
                {
                    Film.AgeNeed = (bool) checkBox.IsChecked;
                }
            }, Film.id, !Film.AgeNeed);
        }

        private void smoothEdit_Clicked(object sender, RoutedEventArgs e)
        {
            DoWork("Смена адаптативности источника", (o, args) => Communication.Proxy.SetFilmIsSmoothStreaming(args.Int, (bool)args.Params[1]), (sender1, eventArgs) =>
            {var checkBox = (CheckBox)sender;
                if (eventArgs.Error != null)
                {
                    

                    checkBox
                        .
                        IsChecked
                        =
                        !checkBox
                             .
                             IsChecked;
                }
                else
                {
                    Film.IsSmoothStreaming = (bool) checkBox.IsChecked;
                }
            }, Film.id, !Film.IsSmoothStreaming);
        }

        private void editSource_Clicked(object sender, RoutedEventArgs e)
        {
            var dlg = new BrowseSource(Film.SourceUri);
            dlg.ShowDialog((o, data) =>
                               {
                                   var str = (string)data;
                                   DoWork("Смена источника",(sender1, args) => Communication.Proxy.SetFilmSource(args.Int,(string) args.Params[1]),(o1, eventArgs) =>
                                                                                       {
                                                                                           if(eventArgs.Error==null)
                                                                                           {
                                                                                               Film.SourceUri = str;
                                                                                               CheckIsFilmBought();
                                                                                           }
                                                                                       },Film.id,str);
                                   
                               });
        }

        private void editTrail_Clicked(object sender, RoutedEventArgs e)
        {
            var dlg = new BrowseSource(Film.TrailerUri);
            dlg.ShowDialog((o, data) =>
                               {
                                   var str = (string) data;
                                   DoWork("Смена трейлера", (sender1, args) => Communication.Proxy.SetFilmTrailer(args.Int,(string) args.Params[1]),(o1, eventArgs) =>
                                                                                       {
                                                                                           if(eventArgs.Error==null)
                                                                                           {
                                                                                               Film.TrailerUri = str;
                                                                                               CheckIsFilmBought();
                                                                                           }
                                                                                       },Film.id,str);
            });
        }

        private void playPrimarySource_Clicked(object sender, RoutedEventArgs e)
        {
            player.SetSource(Film.SourceUri,true,Film.IsSmoothStreaming);
        }

        private void playTrailer_Clicked(object sender, RoutedEventArgs e)
        {
            player.SetSource(Film.TrailerUri,true);
        }


        private void editGenre_Clicked(object sender, MouseButtonEventArgs e)
        {
            if (SecurityBinding.HasPermission(Permission.ChangeFilmAdvanced))
            {
                var dlg = new GenreList() {SelectionMode = GridSelectionMode.SingleRow};
                dlg.ShowDialog(delegate(object o, object data)
                                   {
                                       var genre = (Genre) data;
                                       DoWork("Смена жанра",
                                              (sender1, args) =>
                                              Communication.Proxy.SetFilmGenre(args.Int, (int) args.Params[1]),
                                              (o1, eventArgs) =>
                                                  {
                                                      if (eventArgs.Error == null)
                                                      {
                                                          Film.GenreId = genre.id;
                                                          Film.GenreName = genre.Name;
                                                      }
                                                  }, Film.id, genre.id);
                                   });
            }
        }

        private void goComments_Clicked(object sender, RoutedEventArgs e)
        {
            var dlg = new CommentList(Film.id);
            dlg.ShowDialog();
        }


        private void copyLink_Clicked(object sender, RoutedEventArgs e)
        {
            System.Windows.Clipboard.SetText(((HyperlinkButton)sender).Content.ToString());
        }


        private void rat_Chanched(object sender, RoutedPropertyChangedEventArgs<double?> e)
        {
         if(ratingControl_Loaded)   
            DoWork("Добавление оценки",(o, args) =>
                                           {
                                               args.Result = Communication.Proxy.AddRating(args.Int,
                                                                                           (double) args.Params[1]);
                                           }
                                           ,
                                               (sender1, eventArgs) => 
                                           
                                                 {
                                                     if(eventArgs.Error==null)
                                                     {
                                                         CheckCanRate();
                                                         rateControl.Value = (double) eventArgs.Result;
                                                     }
                                                 },_id,e.NewValue);
         else
         {
             ratingControl_Loaded = true;
         }
        }

        private void deleteFilm_Clicked(object sender, RoutedEventArgs e)
        {
            var dlg = new QuestionBox("После удаления фильма станут недосупными комментарии пользователей и статистика по оплате. Продолжить?"+Film.Name,QuestionBoxType.OkCancel);
            dlg.ShowDialog((o, data) =>
                               {
                                   DoWork("Удаление фильма",(sender1, args) =>
                                                                {
                                                                    Communication.Proxy.DeleteFilm(args.Int);
                                                                },(o1, eventArgs) =>
                                                                      {
                                                                          if(eventArgs.Error==null)
                                                                          {
                                                                              InvokeCancelSelected();
                                                                          }
                                                                      },Film.id);
                               });
        }

        private void close_Clicked(object sender, RoutedEventArgs e)
        {
            InvokeCancelSelected();
        }


        private void mouse_Over(object sender, MouseEventArgs e)
        {
            if(!ratingControl_Loaded)
                ratingControl_Loaded = true;
        }
    }
}
